package socket

import (
	"encoding/json"
	"runtime/debug"
	"sync"

	"qmp_go_push/pkg/logger"
	"qmp_go_push/pkg/response"

	"go.uber.org/zap"
)

// SocketCallable socket
type SocketCallable func(packet *Packet) response.Response

type Packet struct {
	Client *Client
	Exec   string
	Param  map[string]any
}

var (
	handlers        = make(map[string]SocketCallable)
	handlersRWMutex sync.RWMutex
)

func AddHandler(exec string, handler SocketCallable) {
	handlersRWMutex.Lock()
	defer handlersRWMutex.Unlock()
	handlers[exec] = handler
	return
}

func getHandlers(key string) (handler SocketCallable, ok bool) {
	handlersRWMutex.RLock()
	defer handlersRWMutex.RUnlock()
	handler, ok = handlers[key]
	return
}

func HandleFunc(client *Client, message []byte) {
	defer func() {
		if r := recover(); r != nil {
			logger.Error(logger.ErrLogger, "HandleFunc", zap.Any("stack", string(debug.Stack())))
		}
	}()
	packet := &Packet{}
	if err := json.Unmarshal(message, packet); err != nil {
		logger.Info(logger.BizLogger, "HandleFunc", zap.Error(err))
		resp := response.Response{Status: response.ErrParamParse.Code, Message: response.ErrParamParse.Message.Error()}
		res, _ := json.Marshal(resp)
		client.SendMsg(res)
		return
	}

	var responseData response.Response
	handler, ok := getHandlers(packet.Exec)
	if !ok {
		responseData = response.ResponseNotFound()
	} else {
		packet.Client = client
		responseData = handler(packet)

	}
	res, _ := json.Marshal(responseData)
	client.SendMsg(res)
}
